#include "group.h"
#include "user.h"
#include "server.h"
#include "mtm_ex5.h"
#include <complex>
using std::complex;

namespace mtm {
int Group::activityLevel() const {
	complex<double> C(users.size(), recipes.size());
	return std::abs(std::pow(C, 0.25 * BjarneBirthMonth));
}

ostream& operator<<(ostream& os, const Group& group) {
	return os << '(' << group.name << ')';
}

void Group::cleanMemory(unsigned int k) {
	if (recipes.size() > k) {
		recipes.erase(recipes.begin(), recipes.end() - k);
	}
}

Group::Group(const string& name, const shared_ptr<PowerUser>& opener) :
		name(name), leader(opener), users( { opener }) {
}

void Group::joinRequest(const shared_ptr<User>& user) {
	leader->joinRequestUser = user;
}

void Group::leaveRequest(const shared_ptr<User>& user) {
	leader->leaveRequestUser = user;
}

void Group::postRecipe(const shared_ptr<Recipe>& recipe) {
	try {
		getRecipe(recipe->name);
		throw RecipeAlreadyExistsException();
	} catch (NoSuchRecipeInGroupException) {
	}
	recipes.push_back(recipe);
}

shared_ptr<Recipe> Group::getRecipe(const string& recipeName) {
	for (auto& recipe : recipes) {
		if (recipe->name == recipeName) {
			return recipe;
		}
	}
	throw NoSuchRecipeInGroupException();
}

shared_ptr<PowerUser> Group::appointNewLeader() {
	int max = -1;
	shared_ptr < User > *nextLeader = NULL;
	for (auto& user : users) {
		if (user->getDonation() > max && leader != user) {
			nextLeader = &user;
			max = user->getDonation();
		}
	}
	if (nextLeader) {
		leader = Server::getInstance()->makeLeader(*nextLeader);
		*nextLeader = leader;
		return leader;
	} else {
		throw ForeverAloneException();
	}
}

}
